<?php

class Benchmarker
{
    const
        PCHART_FONT_DIR = 'lib/pChart/fonts/'
    ;
    
    
    private
        $bench,
        $methods,
        $results
    ;
    
    // colors
    private $colors = array(
                 'white'   => array('R' => 255,'G' => 255,'B' => 255),
                 'black'   => array('R' =>   0,'G' =>   0,'B' =>   0),
                 'red'     => array('R' => 255,'G' =>   0,'B' =>   0),
                 'green'   => array('R' =>   0,'G' => 100,'B' =>   0),
                 'blue'    => array('R' =>   0,'G' =>   0,'B' => 205),
                 'violet'  => array('R' => 138,'G' =>  43,'B' => 226),
                 'orange'  => array('R' => 255,'G' => 140,'B' =>   0),
                 'grey'    => array('R' => 128,'G' => 128,'B' => 128),
                 'yellow'  => array('R' => 255,'G' => 215,'B' =>   0),
    );
       

    public function __construct(Benchmark $bench)
    {
        $this->bench = $bench;
        $this->methods = array();
        $this->results = array();
    }

    /**
     * Run the benchmark
     * @param int Minimum number of iterations
     * @param int Maximum number of iterations
     * @param int Amount to increment by on each test.
     */
    public function run($max, $step)
    {
        $this->collectMethods();

        foreach ($this->methods as $benchcase => $methodInfo)
        {
            $methodName = $methodInfo['method']->name;
            $result = array();
            
            for ($measurement = 0; $measurement < $max; $measurement += $step)
            {
                $start = microtime(true);
                for ($iterations = 0; $iterations < $measurement; $iterations++)
                {
                    $this->bench->$methodName();
                }
                $duration = floor((microtime(true) - $start) * 1000);
                
                $result[$measurement] = $duration;
            }
            
            $this->results[$benchcase] = array(
                                            'values' => $result,
                                            'color' => $methodInfo['color']
                                         );
        }
    }
    
    private function collectMethods()
    {
        $classInfo = new ReflectionAnnotatedClass($this->bench);
        $methods = $classInfo->getMethods(ReflectionMethod::IS_PUBLIC);
        
        foreach($methods as $method)
        {
            $annotation = $method->getAnnotation('Benchcase');
            if($annotation instanceof Benchcase)
            {
                $benchcase = $annotation->name;
                if($benchcase === null)
                {
                    $benchcase = $method->name;
                }
                
                $this->methods[$benchcase] = array(
                                                'method' => $method,
                                                'color'  => $annotation->color
                                             );
            }
        }
    }
    
    private function getColor($color)
    {
        $return = null;
        if(isset($this->colors[$color]))
        {
            $return = $this->colors[$color];
        }
        
        return $return;
    }
    
    
    // FIXME
    public function publishResults()
    {
        $myData = new pData();
        foreach($this->results as $benchcase => $benchcaseInfo)
        {
            $myData->addPoints($benchcaseInfo['values'], $benchcase);
            $myData->setPalette($benchcase, $this->getColor($benchcaseInfo['color']));
        }

        $myData->setAxisName(0, 'Time');
        $myData->setAbscissa('Iterations');
        
        /* Create the pChart object */
         $myPicture = new pImage($w = 1024, $h = 800, $myData);
        
         /* Add a border to the picture */
         $myPicture->drawRectangle(0, 0, $w -1 , $h - 1, $this->getColor('black'));
          
         /* Write the picture title */
         $font = self::PCHART_FONT_DIR . 'calibri.ttf';
         $myPicture->setFontProperties(array('FontName' => $font, 'FontSize' => 12));
         $myPicture->drawText(10, 13, 'Benchmark', $this->getColor('black'));
         $myPicture->setFontProperties(array('FontName' => $font, 'FontSize' => 10));
        
        
         /* Draw the scale and the 1st chart */
         $myPicture->setGraphArea(60, 60, $w - 60, $h - 60);
         $myPicture->drawScale(array('DrawSubTicks' => true));
         $myPicture->setFontProperties(array('FontName' =>  self::PCHART_FONT_DIR . 'pf_arma_five.ttf', 'FontSize' => 6));
         $myPicture->drawLineChart(array('DisplayValues' => true, 'DisplayColor' => DISPLAY_AUTO));
         $myPicture->setShadow(false);
        
         
         /* Write the chart legend */
         $myPicture->setFontProperties(array('FontName' => $font, 'FontSize' => 10));
         $legendYShift = 20 * count($this->results);
         $myPicture->drawLegend(800, 760 - $legendYShift, array('Style' => LEGEND_NOBORDER, 'Mode' => LEGEND_VERTICAL));
         
         /* Render the picture (choose the best way) */
         $myPicture->autoOutput('pictures/example.drawLineChart.png');
    }
    
    
}
